﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="NHibernateRepository.cs" company="Irdeto">
//   Copyright @ Irdeto 2012
// </copyright>
// <summary>
//   Class:NHibernateRepository{TEntity}
//   Namespace:AOTT.GateWay.DatabaseDao
//   Class Funtion:Represent the class to implement the interface of INHibernateRepository{TEntity}
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using BasicFrameworkDemo.IDAL;
using BasicFrameworkDemo.Utility;

namespace BasicFrameworkDemo.DAL
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;

    using NHibernate;

    /// <summary>
    /// Class:NHibernateRepository{TEntity}
    /// Namespace:AOTT.GateWay.DatabaseDao
    /// Class Funtion:Represent the class to implement the interface of INHibernateRepository{TEntity}
    /// </summary>
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
    /// Creator:zhouchao
    /// Creation Date:11/14/2011 10:33 AM
    /// Modifier:
    /// Last Modified:
    /// ----------------------------------------------------------------------------------------
    public  class NHibernateRepository<TEntity> : IRepository<TEntity>
        where TEntity : class, new()
    {
        /// <summary>
        /// The entity name
        /// </summary>
        private readonly string entityName = typeof (TEntity).Name;

        /// <summary>
        /// Gets the entity queryable.
        /// </summary>
        /// Creator:zhouchao
        /// Creation Date:8/15/2011 10:26 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public IQueryable<TEntity> EntityQueryable
        {
            get { return this.OpenSession().Linq<TEntity>(); }
        }

        /// <summary>
        /// Creates the TEntity
        /// </summary>
        /// <param name="entityList">The entityList</param>
        /// Creator:zhouchao
        /// Creation Date:8/11/2011 3:07 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public void Create(params TEntity[] entityList)
        {
            if (entityList == null || entityList.All(p => p == null))
            {
                return;
            }

            var session = this.OpenSession();
            session.Clear();

            foreach (var entity in entityList.Where(entity => entity != null))
            {
                session.Save(entity);
            }

            this.SaveSession(session);
        }

        /// <summary>
        /// Finds the by id.
        /// </summary>
        /// <param name="id">The id</param>
        /// <returns>
        /// The TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/11/2011 3:07 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public TEntity FindById(int id)
        {
            var session = this.OpenSession();
            return (TEntity)session.Get(typeof(TEntity), id);
        }

        /// <summary>
        /// Removes the TEntity by id.
        /// </summary>
        /// <param name="idList">The idList</param>
        /// Creator:zhouchao
        /// Creation Date:3/2/2012 10:22 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public void Remove(int[] idList)
        {
            if (idList == null || idList.Length == 0)
            {
                return;
            }

            var session = this.OpenSession();
            session.Clear();

            var sql = string.Format(@"delete {0} as entity where entity.id in (:idList)", this.entityName);
            session.CreateQuery(sql).SetParameterList("idList", idList).ExecuteUpdate();
        }

        /// <summary>
        /// Removes the TEntity
        /// </summary>
        /// <param name="entity">The entity</param>
        /// Creator:zhouchao
        /// Creation Date:8/11/2011 3:08 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public void Remove(TEntity entity)
        {
            if (entity == null)
            {
                return;
            }

            var session = this.OpenSession();
            session.Clear();

            session.Delete(entity);

            this.SaveSession(session);
        }

        /// <summary>
        /// Removes the TEntity by expression.
        /// </summary>
        /// <param name="expression">The expression</param>
        /// Creator:zhouchao
        /// Creation Date:3/2/2012 10:22 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public void Remove(Expression<Func<TEntity, bool>> expression)
        {
            var session = this.OpenSession();
            session.Clear();

            var idList = session.Linq<TEntity>().Where(expression).Select(session.GetIdentifier).ToList();
            if (idList.Count == 0)
            {
                return;
            }

            var sql = string.Format(@"delete {0} as entity where entity.id in (:idList)", this.entityName);
            session.CreateQuery(sql).SetParameterList("idList", idList).ExecuteUpdate();
        }

        /// <summary>
        /// Updates the TEntity
        /// </summary>
        /// <param name="entityList">The entityList</param>
        /// Creator:zhouchao
        /// Creation Date:8/11/2011 3:08 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public void Update(params TEntity[] entityList)
        {
            if (entityList == null || entityList.All(p => p == null))
            {
                return;
            }

            var session = this.OpenSession();
            session.Clear();

            foreach (var entity in entityList.Where(entity => entity != null))
            {
                session.Update(entity);
            }

            this.SaveSession(session);
        }

        /// <summary>
        /// Saves the TEntity
        /// </summary>
        /// <param name="entityList">The entityList</param>
        /// Creator:zhouchao
        /// Creation Date:8/11/2011 3:08 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public void Save(params TEntity[] entityList)
        {
            if (entityList == null || entityList.All(p => p == null))
            {
                return;
            }

            var session = this.OpenSession();
            session.Clear();

            foreach (var entity in entityList.Where(entity => entity != null))
            {
                session.SaveOrUpdate(entity);
            }

            this.SaveSession(session);
        }

        /// <summary>
        /// Finds all.
        /// </summary>
        /// <returns>
        /// The list of TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/12/2011 10:30 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public IList<TEntity> FindAll()
        {
            var session = this.OpenSession();
            var entityList = session.Linq<TEntity>().ToList();
            return entityList;
        }

        /// <summary>
        /// Finds the by expression.
        /// </summary>
        /// <param name="expression">The expression</param>
        /// <returns>
        /// The list of TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/18/2011 6:01 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public IList<TEntity> FindByExpression(Expression<Func<TEntity, bool>> expression)
        {
            var session = this.OpenSession();
            var entityList = session.Linq<TEntity>().Where(expression).ToList();
            return entityList;
        }

        /// <summary>
        /// Finds the by expression.
        /// </summary>
        /// <param name="expression">The value of expression indicating</param>
        /// <param name="currentPage">The value of currentPage indicating</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <returns>
        /// The list of TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:11/15/2011 11:51 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public IList<TEntity> FindByExpression(Expression<Func<TEntity, bool>> expression, int currentPage, int pageSize)
        {
            var session = this.OpenSession();
            var entityList = session.Linq<TEntity>().Where(expression).Skip(currentPage * pageSize).Take(pageSize).ToList();
            return entityList;
        }

        /// <summary>
        /// Finds the single by expression.
        /// </summary>
        /// <returns>
        /// The TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/18/2011 9:47 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public TEntity FindSingleByExpression()
        {
            var session = this.OpenSession();
            var entity = session.Linq<TEntity>().FirstOrDefault();
            return entity;
        }

        /// <summary>
        /// Finds the single by expression.
        /// </summary>
        /// <param name="expression">The expression</param>
        /// <returns>
        /// The TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/18/2011 9:47 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public TEntity FindSingleByExpression(Expression<Func<TEntity, bool>> expression)
        {
            var session = this.OpenSession();
            var entity = session.Linq<TEntity>().FirstOrDefault(expression);
            return entity;
        }

        /// <summary>
        /// Finds the by SQL.
        /// </summary>
        /// <param name="hql">The HQL.</param>
        /// <returns>
        /// The list of TEntity
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/16/2011 1:09 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        public IQuery FindIQueryByHql(string hql)
        {
            var query = this.OpenSession().CreateQuery(hql);
            return query;
        }

        /// <summary>
        /// Saves the session.
        /// </summary>
        /// <param name="session">The session</param>
        /// Creator:zhouchao
        /// Creation Date:4/10/2012 5:11 PM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        protected virtual void SaveSession(ISession session)
        {
            session.Flush();
        }

        /// <summary>
        /// Always opens a new session from the session factory.
        /// </summary>
        /// <returns>
        /// The newly opened session.
        /// </returns>
        /// Creator:zhouchao
        /// Creation Date:8/11/2011 9:14 AM
        /// Modifier:
        /// Last Modified:
        /// ----------------------------------------------------------------------------------------
        protected ISession OpenSession()
        {
            var session = FluentNHibernateUtility.GetInstance().GetSession();
            session.FlushMode = FlushMode.Commit;
            return session;
        }
    }
}